﻿using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
using System.Reflection;
using System.Text;

[Serializable]
public class MetaTableLoad<T> {
    public List<T> data = new List<T>(); //必须为public
    Dictionary<int, int> int_index;
    Dictionary<string, int> str_index;

    bool indexCache(FieldInfo fi, int i) {
        object id_obj = fi.GetValue(data[i]);
        int id_int = Convert.ToInt32(id_obj);
        if(id_int == 0) {
            //主键为string类型
            if(str_index == null) {
                str_index = new Dictionary<string, int>();
            }
            string id_str = id_obj.ToString();
            if(string.IsNullOrEmpty(id_str)) {
                Debug.LogError(string.Format("解析Meta Id : {0} 无效！Class: {1}", id_str, typeof(T).Name));
            }
            if(str_index.ContainsKey(id_str)) {
                Debug.LogError(string.Format("Meta Id : {0} 重复！Class: {1}", id_str.ToString(), typeof(T).Name));
            };
            str_index.Add(id_str, i);
        }
        else {
            //主键为int类型
            if(int_index == null) {
                int_index = new Dictionary<int, int>();
            }
            if(int_index.ContainsKey(id_int)) {
                Debug.LogError(string.Format("Meta Id : {0} 重复！Class: {1}", id_int.ToString(), typeof(T).Name));
            };
            int_index.Add(id_int, i);
        }

        return true;
    }
    public void Init(MTAssembler assembler) {
        FieldInfo fi = typeof(T).GetField("meta_id");

        for (int i = 0; i < data.Count; i++) {
            indexCache(fi, i); //建立反向索引
            if(assembler != null) {  //执行数据组装
                assembler(data[i]);
            }
        }
    }
    public T GetData(int meta_id) {
        int idx = 0;
        if (int_index != null 
                && int_index.TryGetValue(meta_id, out idx)) {
            return data[idx];
        }
        return default(T);
    }
    public T GetData(string meta_id) {
        int idx = 0;
        if (str_index != null 
                && str_index.TryGetValue(meta_id, out idx)) {
            return data[idx];
        }
        return default(T);
    }
}
[Serializable]
public class MetaTableListLoad {
    //数据表格文件名记录
    public List<string> list = new List<string>();
}

public delegate void MTAssembler(object data);  //数据组装函数
public class JsonManager : MonoBehaviour {  //todo 修改为项目中的单例

    Dictionary<E_METATABLE_ID, object> m_metaMgrs = new Dictionary<E_METATABLE_ID, object>();
    MetaTableListLoad fileNameList;
    readonly string JSON_FILE_LIST = "metatable_list.json"; //数据表格文件名记录，与E_METATABLE_ID枚举顺序对应

    void Start() {
        Init();
    }
    private bool flag = false;
    void Update() {
        if (Input.GetKeyUp(KeyCode.A)) {
            RegisterData<MT_Quest_QuestMain>(E_METATABLE_ID.MT_ID_QUEST_QUESTMAIN);
            RegisterData<MT_Quest_QuestCommon>(E_METATABLE_ID.MT_ID_QUEST_QUESTCOMMON);
            RegisterData<MT_Quest_QuestRepeat>(E_METATABLE_ID.MT_ID_QUEST_QUESTREPEAT);
            RegisterData<MT_Currency_CurrencyConfig>(E_METATABLE_ID.MT_ID_CURRENCY_CURRENCYCONFIG);
            RegisterData<MT_String_NoticeString>(E_METATABLE_ID.MT_ID_STRING_NOTICESTRING);
        }
        if (Input.GetKeyUp(KeyCode.S)) {
            flag = !flag;
        }
        if (flag) {
            //MT_Quest_QuestCommon cfg = GetMetaDataTable<MT_Quest_QuestCommon>(E_METATABLE_ID.MT_ID_QUEST_QUESTCOMMON, (int)E_MT_COMMONDEFINE_COMMONCURRENCY.CAT_COIN);
            MT_String_NoticeString cfg = GetMetaDataTable<MT_String_NoticeString>(E_METATABLE_ID.MT_ID_STRING_NOTICESTRING, "QUEST_LEVEL_MEET");
        }
    }
    private bool _metaIdValid(E_METATABLE_ID mng_id) {
        if (mng_id < E_METATABLE_ID.MT_ID_START || mng_id >= E_METATABLE_ID.MT_ID_END) {
            Debug.LogError(string.Format("{0}无效Meta Id", mng_id));
            return false;
        }
        return true;
    }
    public bool Init() {
        DirectoryInfo dirInfo = new DirectoryInfo(Application.dataPath);
        string list_path = Path.Combine(dirInfo.Parent.ToString(), string.Format("Data\\json\\{0}", JSON_FILE_LIST));
        FileStream fs = new FileStream(list_path, FileMode.Open, FileAccess.Read);
        StreamReader sr = new StreamReader(fs);
        fileNameList = JsonUtility.FromJson<MetaTableListLoad>(sr.ReadToEnd());
        return true;
    }
    public bool RegisterData<T>(E_METATABLE_ID mng_id, MTAssembler assembler = null) {
        if (!_metaIdValid(mng_id)) return false;

        DirectoryInfo dirInfo = new DirectoryInfo(Application.dataPath);
        string file_path = Path.Combine(dirInfo.Parent.ToString(), string.Format("Data\\json\\{0}", fileNameList.list[(int)mng_id]));

        FileStream fs = new FileStream(file_path, FileMode.Open, FileAccess.Read);
        byte[] buffer = new byte[fs.Length];
        fs.BeginRead(buffer, 0, (int)fs.Length, (result) =>
        {
            if (result.IsCompleted) {
                fs.EndRead(result);
                MetaTableLoad<T> metaMgr = JsonUtility.FromJson<MetaTableLoad<T>>(Encoding.UTF8.GetString(buffer));
                metaMgr.Init(assembler);
                m_metaMgrs.Add(mng_id, metaMgr);
            }
        }, null);
        return true;
    }
    public T GetMetaDataTable<T>(E_METATABLE_ID mng_id, int meta_id) {
        if (!_metaIdValid(mng_id)) return default(T);
        object meta;
        if (m_metaMgrs.TryGetValue(mng_id, out meta)) {
            MetaTableLoad<T> mt = meta as MetaTableLoad<T>;
            return mt.GetData(meta_id);
        }
        return default(T);
    }
    public T GetMetaDataTable<T>(E_METATABLE_ID mng_id, string meta_id) {
        if (!_metaIdValid(mng_id)) return default(T);
        object meta;
        if (m_metaMgrs.TryGetValue(mng_id, out meta)) {
            MetaTableLoad<T> mt = meta as MetaTableLoad<T>;
            return mt.GetData(meta_id);
        }
        return default(T);
    }

}
